package com.ctyon.watchmanager.ui.activity;

import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.fastjson.JSON;
import com.ctyon.common.event.ChangeWatch;
import com.ctyon.common.event.UpdateApp;
import com.ctyon.common.util.SPUtils;
import com.ctyon.netlibrary.net.revert.BaseResponseEntity;
import com.ctyon.netlibrary.use.BaseObserver;
import com.ctyon.watchmanager.BasicApp;
import com.ctyon.watchmanager.R;
import com.ctyon.watchmanager.listener.ItemClickListener;
import com.ctyon.watchmanager.model.net.entity.Watch;
import com.ctyon.watchmanager.model.net.service.NetService;
import com.ctyon.watchmanager.service.BgService;
import com.ctyon.watchmanager.ui.BaseActivity;
import com.ctyon.watchmanager.ui.BaseFragment;
import com.ctyon.watchmanager.ui.adapter.WatchListAdapter;
import com.ctyon.watchmanager.ui.fragment.HomeFragment;
import com.ctyon.watchmanager.ui.fragment.MineFragment;
import com.ctyon.watchmanager.util.AppUtil;
import com.ctyon.watchmanager.util.DirectoryUtils;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.orhanobut.logger.Logger;
import com.tbruyelle.rxpermissions2.RxPermissions;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AlertDialog;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import lee.com.mqttlibrary.mqtt.MQTTManager;

import static com.ctyon.common.container.ARouterPath.ROUTER_ACTIVITY_MAIN;
import static com.ctyon.common.util.SPUtils.WATCH_ID;

@Route(path = ROUTER_ACTIVITY_MAIN)
public class MainActivity extends BaseActivity {

    private final static int TAB_INDEX_HOME = 0;
    private final static int TAB_INDEX_MINE = 1;

    private Drawable watchSelect;
    private Drawable watchNormal;

    private int tabIndex;
    private BottomNavigationView navigation;
    private DrawerLayout drawer;
    private AlertDialog.Builder builder;

    private Map<Integer, BaseFragment> tabMap = new LinkedHashMap<>(2);
    private FragmentManager fragmentManager;

    private List<Watch> watchList = new ArrayList<>();

    private WatchListAdapter watchListAdapter;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = menuItem -> {
        switch (menuItem.getItemId()) {
            case R.id.navigation_home:
                Logger.i("navigation_home");
                loadFragment(TAB_INDEX_HOME);
                return true;
            case R.id.navigation_mine:
                Logger.i("navigation_mine");
                loadFragment(TAB_INDEX_MINE);
                return true;
        }
        return false;
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();

        if (savedInstanceState == null) {

            Logger.d("init home");

            HomeFragment fragment = HomeFragment.newInstance();
            fragmentManager
                    .beginTransaction()
                    .add(R.id.fragment_container, fragment, HomeFragment.TAG)
                    .commit();

            tabIndex = TAB_INDEX_HOME;
            navigation.setEnabled(true);

            tabMap.put(tabIndex, fragment);
        }

        new RxPermissions(this).request(
                Manifest.permission.INTERNET,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(granted -> {
                    Logger.i("rxPermissions : granted = " + granted);
                    if (granted) { // Always true pre-M
                        Logger.d("startBgService");
                        startService(new Intent(this, BgService.class));
                        EventBus.getDefault().register(this);
                    } else {
                        Logger.d("rxPermissions failed");
                    }
                });

    }

    private void init() {
        Logger.d("init begin");

        fragmentManager = getSupportFragmentManager();
        navigation = findViewById(R.id.navigation);
        navigation.setEnabled(false);
        navigation.setItemIconTintList(null);    //删除默认的选中效果
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        navigation.setSelectedItemId(R.id.navigation_home);

        Logger.d("init over");
    }

    public void addFragment(BaseFragment fragment, int currentIndex, String tag) {
        Log.d("Lee_MainActivity", "addFragment");
        fragmentManager
                .beginTransaction()
                .hide(tabMap.get(tabIndex))
                .add(R.id.fragment_container, fragment, tag)
                .commit();

        tabIndex = currentIndex;
        tabMap.put(tabIndex, fragment);
    }

    public void showFragment(int currentIndex) {
        Log.d("Lee_MainActivity", "showFragment");
        fragmentManager
                .beginTransaction()
                .hide(tabMap.get(tabIndex))
                .show(tabMap.get(currentIndex))
                .commit();

        tabIndex = currentIndex;
    }

    private void loadFragment(int tab) {
        navigation.setEnabled(false);
        if (TAB_INDEX_HOME == tab && TAB_INDEX_HOME != tabIndex) {
            HomeFragment homeFragment = (HomeFragment) fragmentManager.findFragmentByTag(HomeFragment.TAG);
            if (null == homeFragment) {
                Logger.i("add HomeFragment");
                homeFragment = HomeFragment.newInstance();
                addFragment(homeFragment, TAB_INDEX_HOME, HomeFragment.TAG);
            } else {
                Logger.i("show HomeFragment");
                showFragment(TAB_INDEX_HOME);
            }
        } else if (TAB_INDEX_MINE == tab && TAB_INDEX_MINE != tabIndex) {
            MineFragment mineFragment = (MineFragment) fragmentManager.findFragmentByTag(MineFragment.TAG);
            if (null == mineFragment) {
                Logger.i("add MineFragment");
                mineFragment = MineFragment.newInstance();
                addFragment(mineFragment, TAB_INDEX_MINE, MineFragment.TAG);
            } else {
                Logger.i("show MineFragment");
                showFragment(TAB_INDEX_MINE);
            }
        }
        navigation.setEnabled(true);
    }

    @Override
    public void onBackPressed() {
        Logger.d("onBackPressed");
        if (null != drawer && drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            moveTaskToBack(false);
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    private final ItemClickListener<Integer> itemClickListener = (index) -> {
        Logger.d("id = " + index);
        if (watchList.size() == 0) {
            return;
        }
        String meid = watchList.get(index).getMeid();
        if (meid.equals(BasicApp.getInstance().getWatch().getMeid())) {
            return;
        }
        SPUtils.getInstance().put(WATCH_ID, watchList.get(index).getMeid());
        BasicApp.getInstance().setWatch(watchList.get(index));
        refreshWatchList();
        EventBus.getDefault().post(new ChangeWatch());

        drawer.closeDrawers();
    };

    public void openDrawer() {
        Logger.d("openDrawer");
        if (null == drawer) {

            Observable.create((ObservableOnSubscribe) emitter -> {
                Logger.d("init drawer");
                watchSelect = getResources().getDrawable(R.mipmap.change_watch_select);
                watchNormal = getResources().getDrawable(R.mipmap.change_watch_normal);
                emitter.onNext(emitter);
            }).subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(o -> {
                        drawer = findViewById(R.id.drawer_layout);
                        drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
                        RecyclerView recyclerView = findViewById(R.id.watch_recycle);
                        watchListAdapter = new WatchListAdapter(itemClickListener);
                        LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
                        layoutManager.setOrientation(RecyclerView.VERTICAL);
                        recyclerView.setLayoutManager(layoutManager);
                        recyclerView.setAdapter(watchListAdapter);
                        openDrawer();
                    });
        } else {
            drawer.openDrawer(GravityCompat.START);
            NetService.getInstance()
                    .getWatchList(BasicApp.getInstance().getManager().getManagerId())
                    .delay(200, TimeUnit.MILLISECONDS)
                    .subscribeOn(Schedulers.io())
                    .subscribe(new BaseObserver<BaseResponseEntity>() {
                        @Override
                        public void onSuccess(BaseResponseEntity responseEntity) {
                            Logger.d("onSuccess : " + responseEntity.data.toString());
                            if (null != responseEntity.data) {

                                String data = responseEntity.data.toString();
                                Logger.d("data : " + data);
                                if (data.contains("=")) {
                                    data = data.replace("=", ":");
                                }
                                if (data.contains(":,")) {
                                    data = data.replace(":,", ":null,");
                                }
                                if (data.contains(":}")) {
                                    data = data.replace(":}", ":null}");
                                }
                                Logger.d("data : " + data);

                                watchList.clear();

                                try {
                                    JSONArray jsonArray = new JSONArray(data);
                                    for (int i = 0; i < jsonArray.length(); i++) {
                                        org.json.JSONObject obj = jsonArray.getJSONObject(i);
                                        Logger.d("obj : " + obj.toString());
                                        Watch watch = JSON.parseObject(obj.toString(), Watch.class);
                                        String meid = watch.getMeid();
                                        StringBuilder sb = new StringBuilder();
                                        for (int j = 0; j < 10 - meid.length(); j++) {
                                            sb.append("0");
                                        }
                                        sb.append(meid);
                                        watch.setMeid(sb.toString());
                                        watchList.add(watch);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }

                                refreshWatchList();
                            }
                        }
                    });
        }
    }

    private void refreshWatchList() {
        Observable.create(emitter -> {
            String watchId = SPUtils.getInstance().getString(WATCH_ID);
            for (Watch watch : watchList) {
                Logger.d("watchId = " + watchId + " meid = " + watch.getMeid());
                if (watch.getMeid().equals(watchId)) {
                    watch.setDrawable(watchSelect);
                } else {
                    watch.setDrawable(watchNormal);
                }
            }
            emitter.onNext(emitter);
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(o -> watchListAdapter.setWatchList(watchList));
    }

    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    public void onDownloadApkSuccess(UpdateApp updateApp) {
        Logger.d("onDownloadApkSuccess");
        showDialog(updateApp.getPath());
    }

    private void showDialog(String path) {
        if (null == builder) {
            builder = new AlertDialog.Builder(this, R.style.MyDialog);
            builder.setTitle("版本更新")
                    .setMessage("发现新版本,点击确定安装更新")
                    .setPositiveButton("下次再说", (dialog, which) -> {

                    })
                    .setNegativeButton("确定", (dialog, which) -> {
                        AppUtil.install(BasicApp.getInstance().getApplicationContext(), path);
                    });
        }
        builder.show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        MQTTManager.getInstance().unBindMQTTService();
    }
}
